package utils

import (
	"encoding/json"
	"fmt"
	"net/http"
	"reflect"
	"strconv"
	"strings"
)

// PatchUpdate 泛型Patch更新函数
func PatchUpdate[T any](existing *T, updateData map[string]interface{}, ignoreFields []string) error {
	if existing == nil {
		return fmt.Errorf("existing object cannot be nil")
	}

	existingValue := reflect.ValueOf(existing).Elem()
	existingType := existingValue.Type()

	// 创建忽略字段的map
	ignoreMap := make(map[string]bool)
	for _, field := range ignoreFields {
		ignoreMap[field] = true
	}

	// 遍历更新数据
	for key, newValue := range updateData {
		// 检查是否忽略该字段
		if ignoreMap[key] {
			continue
		}

		// 查找字段
		field, found := existingType.FieldByNameFunc(func(fieldName string) bool {
			field, _ := existingType.FieldByName(fieldName)
			jsonTag := field.Tag.Get("json")
			if jsonTag != "" {
				// 处理json标签中的omitempty等选项
				jsonName := strings.Split(jsonTag, ",")[0]
				return jsonName == key
			}
			return fieldName == key
		})

		if !found {
			// 字段不存在，跳过
			continue
		}

		// 检查字段是否可设置
		fieldValue := existingValue.FieldByName(field.Name)
		if !fieldValue.CanSet() {
			continue
		}

		// 处理特殊字段类型
		if err := setFieldValue(fieldValue, newValue, field.Type); err != nil {
			return fmt.Errorf("failed to set field %s: %v", key, err)
		}
	}

	return nil
}

// setFieldValue 设置字段值，处理类型转换
func setFieldValue(field reflect.Value, value interface{}, fieldType reflect.Type) error {
	if value == nil {
		// 对于指针字段，设置为nil
		if field.Kind() == reflect.Ptr {
			field.Set(reflect.Zero(fieldType))
			return nil
		}
		// 非指针字段不能设置为nil
		return nil
	}

	valueReflect := reflect.ValueOf(value)
	valueType := valueReflect.Type()

	// 如果类型匹配，直接设置
	if valueType.AssignableTo(fieldType) {
		field.Set(valueReflect)
		return nil
	}

	// 处理类型转换
	switch field.Kind() {
	case reflect.String:
		if valueType.ConvertibleTo(fieldType) {
			field.Set(valueReflect.Convert(fieldType))
		} else {
			field.Set(reflect.ValueOf(fmt.Sprintf("%v", value)))
		}

	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		switch v := value.(type) {
		case float64: // JSON数字默认是float64
			field.SetInt(int64(v))
		case int:
			field.SetInt(int64(v))
		case int64:
			field.SetInt(v)
		case string:
			if intValue, err := strconv.ParseInt(v, 10, 64); err == nil {
				field.SetInt(intValue)
			}
		default:
			return fmt.Errorf("cannot convert %T to int", value)
		}

	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
		switch v := value.(type) {
		case float64:
			field.SetUint(uint64(v))
		case int:
			field.SetUint(uint64(v))
		case string:
			if uintValue, err := strconv.ParseUint(v, 10, 64); err == nil {
				field.SetUint(uintValue)
			}
		default:
			return fmt.Errorf("cannot convert %T to uint", value)
		}

	case reflect.Float32, reflect.Float64:
		switch v := value.(type) {
		case float64:
			field.SetFloat(v)
		case int:
			field.SetFloat(float64(v))
		case string:
			if floatValue, err := strconv.ParseFloat(v, 64); err == nil {
				field.SetFloat(floatValue)
			}
		default:
			return fmt.Errorf("cannot convert %T to float", value)
		}

	case reflect.Bool:
		switch v := value.(type) {
		case bool:
			field.SetBool(v)
		case string:
			if boolValue, err := strconv.ParseBool(v); err == nil {
				field.SetBool(boolValue)
			}
		default:
			return fmt.Errorf("cannot convert %T to bool", value)
		}

	case reflect.Slice:
		// 处理空数组
		if value == nil {
			field.Set(reflect.MakeSlice(fieldType, 0, 0))
			return nil
		}

		if valueReflect.Kind() == reflect.Slice {
			newSlice := reflect.MakeSlice(fieldType, valueReflect.Len(), valueReflect.Len())
			for i := 0; i < valueReflect.Len(); i++ {
				elemValue := valueReflect.Index(i)
				if err := setFieldValue(newSlice.Index(i), elemValue.Interface(), fieldType.Elem()); err != nil {
					return err
				}
			}
			field.Set(newSlice)
		}

	case reflect.Ptr:
		// 创建新的指针对象
		newValue := reflect.New(fieldType.Elem())
		if err := setFieldValue(newValue.Elem(), value, fieldType.Elem()); err != nil {
			return err
		}
		field.Set(newValue)

	default:
		// 尝试类型转换
		if valueType.ConvertibleTo(fieldType) {
			field.Set(valueReflect.Convert(fieldType))
		} else {
			return fmt.Errorf("cannot convert %s to %s", valueType, fieldType)
		}
	}

	return nil
}

// ParsePatchData 解析Patch请求数据
func ParsePatchData(r *http.Request) (map[string]interface{}, error) {
	var updateData map[string]interface{}
	if err := json.NewDecoder(r.Body).Decode(&updateData); err != nil {
		return nil, fmt.Errorf("invalid JSON: %v", err)
	}
	return updateData, nil
}

// GetDefaultIgnoreFields 获取默认忽略的字段
func GetDefaultIgnoreFields() []string {
	return []string{"id", "created", "updated", "deleted"}
}